package com.ap.core.jbehave.retrievertp;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;

import java.math.BigDecimal;

import org.hamcrest.CoreMatchers;
import org.jbehave.core.annotations.Given;
import org.jbehave.core.annotations.Then;
import org.jbehave.core.annotations.When;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ap.core.cxf.jaxb.common.APCORE1FaultDetailsType;
import com.ap.core.cxf.jaxb.common.DeliveryType;
import com.ap.core.cxf.jaxb.managepayment.RetrieveRTP1Request;
import com.ap.core.cxf.jaxb.managepayment.RetrieveRTP1Response;
import com.ap.core.cxf.jaxb.managertp.SubmitRTP1Request;
import com.ap.core.cxf.jaxb.managertp.SubmitRTP1Response;
import com.ap.core.cxf.jaxb.managertp.SubmitRTPMessageType;
import com.ap.core.cxf.jaxb.msghdr.MessageType;
import com.ap.core.cxf.jaxb.rtp.TransactionCheckOutType;
import com.ap.core.jbehave.BaseTransitionRTPSteps;
import com.ap.core.jbehave.StoryContext;
import com.ap.core.util.JaxbUtil;
import com.ap.core.util.Nullable;
import com.ap.core.util.TypedKey;
import com.ap.generator.retrievertp.RetrieveRTPRequestTypeGeneratorBuilder;
import com.core.ap.wsdl.managepaymentservice_1.ManagePayment1PortType;
import com.core.ap.wsdl.managepaymentservice_1.RetrieveRTP1Fault;
import com.core.ap.wsdl.managertpservice_1.ManageRTP1PortType;
import com.core.ap.wsdl.managertpservice_1.SubmitRTP1Fault;

public class RetrieveRTPForBRNFaultSteps extends BaseTransitionRTPSteps {

	public static final TypedKey<Nullable<String>> brn = new TypedKey<>("BRN");
	public static final TypedKey<Nullable<MessageType>> messageType = new TypedKey<>("MessageType");
	public static final TypedKey<SubmitRTP1Request> REQUEST_TYPE = new TypedKey<>("Request Type");
	public static final TypedKey<SubmitRTP1Response> RESPONSE_TYPE = new TypedKey<>("Response Type");

	private static final Logger LOG = LoggerFactory.getLogger(RetrieveRTPForBRNFaultSteps.class);

	public RetrieveRTPForBRNFaultSteps(StoryContext storyContext) {
		super(storyContext);
	}

	@Given("The Consumer chosen to pay by Zapp Online AND sent some invalidate information for BRN")
	public void givenConsumerAuthoriseThePayment() {
		LOG.info("Given The Consumer chosen to pay by Zapp Online AND sent some invalidate information for BRN");
	}

	@When("The Distributor submits erroneous info to the AP server w.r.t BRN journey")
	public void whenASubmitRTPRequestisMade() throws Exception {
		LOG.info("When The Distributor submits erroneous info to the AP server w.r.t BRN journey");
		
		SubmitRTP1Response submitRTP1Response = performSubmitRTPOperation();
		
		final ManagePayment1PortType managePayment1PortType = factory.getBean(ManagePayment1PortType.class);
		
		RetrieveRTP1Request retrieveRTP1Request = constructRetrieveRTP1Request(submitRTP1Response);	
		retrieveRTP1Request.getRequestInfo().setFIId(null);
		JaxbUtil.newInstance().javaToXML(RetrieveRTP1Request.class,	retrieveRTP1Request);
		

		checkFault(new TypedKey<RetrieveRTP1Fault>("RV0005"),managePayment1PortType, retrieveRTP1Request);
		
		LOG.info("When -  Response Received");

	}
	
	@Then("The AP Server should send the appropriate BRN journey fault information back to OSB")
	public void thenResponseWasReceivedWithBRN() {

		LOG.info("Then - The AP Server should send the appropriate BRN journey fault information back to OSB");

		for (TypedKey<RetrieveRTP1Fault> key : storyContext.keySet()) {
			APCORE1FaultDetailsType fault = storyContext.get(key).getFaultInfo();		
			StringBuilder stringBuilder = new StringBuilder(150);
	    	stringBuilder.append("\n FaultString:"+fault.toString());
	    	stringBuilder.append(" FaultId:"+fault.getFaultid());
	    	stringBuilder.append("\n"+" Errorcode:"+fault.getErrorcode());
	        stringBuilder.append( " ErrorMessage:"+fault.getErrormessage());
	        stringBuilder.append("\n"+" InternalErrorCode:"+fault.getInternalcode());
	        stringBuilder.append(" InternalErrorMessage:"+fault.getInternalmessage());
	        String message = stringBuilder.toString();
			LOG.info("\n\nFault Error Details for "	+key+ " :"+ message+"\n");
			JaxbUtil.newInstance().javaToXML(APCORE1FaultDetailsType.class, fault);
			
	        assertThat("Fault Id is not as expected", false, CoreMatchers.is(equalTo(fault.getFaultid() == null)));
	        assertThat("Error code is not as expected",	false,	CoreMatchers.is(equalTo(fault.getErrorcode() == null)));
	        assertThat("Error Message is not as expected", false, CoreMatchers.is(equalTo(fault.getErrormessage() == null)));
	        assertThat("Internal Code is not as expected", false, CoreMatchers.is(equalTo(fault.getInternalcode() == null)));
	        assertThat("Internal Message is not as expected", false, CoreMatchers.is(equalTo(fault.getInternalmessage() == null)));
		}

	}

	private SubmitRTP1Response performSubmitRTPOperation()	throws SubmitRTP1Fault {
		final ManageRTP1PortType manageRTP1PortType = factory.getBean(ManageRTP1PortType.class);
		SubmitRTP1Request submitRTPRequest = generateSubmitRTPRequest(SubmitRTPMessageType.SUBMITRTPFORBRN, "000001", "000001",	TransactionCheckOutType.NRMLCHK, BigDecimal.TEN, true, false);		
		JaxbUtil.newInstance().javaToXML(SubmitRTP1Request.class, submitRTPRequest);		
		
		SubmitRTP1Response submitRTP1Response = manageRTP1PortType.submitRTP1(submitRTPRequest);
		JaxbUtil.newInstance().javaToXML(SubmitRTP1Response.class,	submitRTP1Response);
		
		return submitRTP1Response;
	}
	
	
	 protected RetrieveRTP1Request constructRetrieveRTP1Request(SubmitRTP1Response responseRTPType) {
			RetrieveRTP1Request retrieveRTP1Request = RetrieveRTPRequestTypeGeneratorBuilder.getRetrieveRTPTypeGenerator().build().generate();
	        if(null == responseRTPType.getResponseInfo().getBRN()){
	            retrieveRTP1Request.getRequestInfo().setApTransactionId(responseRTPType.getResponseInfo().getApTransactionId());
	            retrieveRTP1Request.getRequestInfo().setApTRId(responseRTPType.getResponseInfo().getApTRId());
	            retrieveRTP1Request.getRequestInfo().setBRN(null); 
	        }else{
	            retrieveRTP1Request.getRequestInfo().setApTransactionId(null);
	            retrieveRTP1Request.getRequestInfo().setApTRId(null);
	            retrieveRTP1Request.getRequestInfo().setBRN(responseRTPType.getResponseInfo().getBRN());            
	        }
	        retrieveRTP1Request.getRequestInfo().setFIId("000002");
	        retrieveRTP1Request.getRequestInfo().setFIConsumerId("hsbccon2");
			return retrieveRTP1Request;
		}

	private void checkFault(TypedKey<RetrieveRTP1Fault> FAULT,	final ManagePayment1PortType managePayment1PortType,
			RetrieveRTP1Request retrieveRTPRequest) {
		try {
			
			RetrieveRTP1Response retrieveRTPResponse = managePayment1PortType.retrieveRTP1(retrieveRTPRequest);
			LOG.info("When -  Response Received");
			JaxbUtil.newInstance().javaToXML(RetrieveRTP1Response.class, retrieveRTPResponse);
			
		} catch (RetrieveRTP1Fault fault) {
			storyContext.put(FAULT, fault);
		}
	}

	private SubmitRTP1Request generateSubmitRTPRequest(SubmitRTPMessageType messageType,
			String distributorId, String merchantId,
			TransactionCheckOutType transactionCheckOutType,
			BigDecimal totalPaymentReqAmount, boolean isDeliveryRequired,
			boolean isDeliveryAddressRequired) {
		SubmitRTP1Request submitRTPRequest = createSubmitRTPRequest(messageType);

		submitRTPRequest.getRTPSenderInfo().getDistributorInfo().setDistributorId(distributorId);
		submitRTPRequest.getRTPSenderInfo().getDetailMerchantInfo().getMerchantInfo().setMerchantId(merchantId);
		submitRTPRequest.getRTPSummary().setTxCheckout(transactionCheckOutType);
		submitRTPRequest.getRTPSummary().getPaymtAmtInfo().setTotalPaymentReqAmount(totalPaymentReqAmount);
		
		submitRTPRequest.getDelivery().setDeliveryType(DeliveryType.DELTAD);

		LOG.info("When -  The Distributor submits erroneous info to the AP server w.r.t BRN journey");
		JaxbUtil.newInstance().javaToXML(SubmitRTP1Request.class, submitRTPRequest);
		return submitRTPRequest;
	}

	
}
